#ifndef __UART0FIFO_H_202132131312546543
#define __UART0FIFO_H_202132131312546543

#define UAFIFO_RX_FIFO_SIZE       512     // FIFO size of software RX FIFO
#define UAFIFO_TX_FIFO_SIZE       512     // FIFO size of software TX FIFO

#define _UAFIFO_RXP_ROUND(x)        if(x >= UAFIFO_RX_FIFO_SIZE) x = 0
#define _UAFIFO_TXP_ROUND(x)        if(x >= UAFIFO_TX_FIFO_SIZE) x = 0


extern uint8_t g_u8UAFIFO_RxFifo[UAFIFO_RX_FIFO_SIZE];
extern uint8_t g_u8UAFIFO_TxFifo[UAFIFO_RX_FIFO_SIZE];
extern int32_t g_i32UAFIFO_RxFifoHead;
extern int32_t g_i32UAFIFO_RxFifoTail;
extern int32_t g_i32UAFIFO_TxFifoHead;
extern int32_t g_i32UAFIFO_TxFifoTail;


static __INLINE int32_t UAFIFO_Read(uint8_t *pu8Buf, int32_t size)
{
    int32_t i;
    int32_t i32Head;
    
    i32Head = g_i32UAFIFO_RxFifoHead;
    i = 0;
    while(i32Head != g_i32UAFIFO_RxFifoTail) // check if FIFO empty
    {
        if(i < size)
        {
            // Pop data from Rx FIFO
            pu8Buf[i++] = g_u8UAFIFO_RxFifo[g_i32UAFIFO_RxFifoTail++];
            _UAFIFO_RXP_ROUND(g_i32UAFIFO_RxFifoTail);
        }
        else
            break;
    }
    
    return i;
}


static __INLINE int32_t UAFIFO_Write(uint8_t *pu8Buf, int32_t size)
{
    int32_t i32Tmp, i32Tail, i;

    i32Tail = g_i32UAFIFO_TxFifoTail;
    i = 0;
    do
    {
        i32Tmp = g_i32UAFIFO_TxFifoHead + 1;
        _UAFIFO_TXP_ROUND(i32Tmp);

        // check if FIFO full
        if(i32Tmp == i32Tail)
            break;
        
        // Push data to Tx FIFO         
        g_u8UAFIFO_TxFifo[g_i32UAFIFO_TxFifoHead++] = pu8Buf[i++];
        _UAFIFO_TXP_ROUND(g_i32UAFIFO_TxFifoHead);

    }while(i < size);

    return i;
}


void UAFIFO_TriggerTx(void);
void UAFIFO_InitUART0(void);
void UAFIFO_ResetFifo(void);

#endif //__UART_FIFO_H__


	  

#endif


